package jee.boot.common.remote;

import jee.boot.common.basic.ServiceException;
import jee.boot.common.basic.result.MapData;
import jee.boot.common.basic.result.ResponseMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpMethod;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 进程内部请求访问,在单节点部署的情况下使用当前实现,默认配置
 */
public class ProcessInternalRequest implements RemoteEndpoint {
    private Logger logger = LoggerFactory.getLogger(getClass());

    private LocalProcessInternalRequest localProcessInternalRequest;

    public void setLocalProcessInternalRequest(LocalProcessInternalRequest localProcessInternalRequest) {
        this.localProcessInternalRequest = localProcessInternalRequest;
    }

    /**
     * 检查本地是否存在当前请求实例,如果存在,返回true
     *
     * @param path
     * @return
     */
    public boolean isProcessInternalRequest(String path) {
        return localProcessInternalRequest.getEndpointMap().containsKey(path);
    }

    /**
     * @param serviceId    远程服务id,
     * @param path         远程服务path
     * @param param        请求参数
     * @param responseType 返回数据类型设定
     * @return 返回响应数据
     */
    @Override
    public <T> T executePost(String serviceId, String path, Object param, Class<?> responseType) {
        LocalProcessInternalRequest.Endpoint endpoint = localProcessInternalRequest.getEndpointMap().get(path);
        if (endpoint == null) {
            throw new ServiceException(1308, MapData.instance().put("path", serviceId + path).data());
        }
        HttpMethod httpMethod = endpoint.getHttpMethod();
        if (httpMethod != null && !HttpMethod.POST.equals(httpMethod)) {
            throw new ServiceException(1309, MapData.instance().put("path", serviceId + path).data());
        }
        Method method = endpoint.getMethod();
        String localName = method.getDeclaringClass().getName() + "." + method.getName();
        try {
            logger.info("本地服务[" + localName + "]");
            Object invoke = method.invoke(endpoint.getClassInstance(), param);
            if (invoke != null) {
                if (invoke instanceof ResponseMessage) {
                    return ((ResponseMessage<T>) invoke).getData();
                } else {
                    return (T) invoke;
                }
            }
            return (T) responseType.newInstance();
        } catch (InvocationTargetException e) {
            logger.error("本地服务[" + localName + "]异常," + e.getTargetException().getMessage(), e.getTargetException());
            throw new ServiceException(1310, MapData.instance().put("path", localName).data());
        } catch (Exception e) {
            logger.error("本地服务[" + localName + "]异常," + e.getMessage(), e);
            throw new ServiceException(1310, MapData.instance().put("path", localName).data());
        }
    }

    @Override
    public <T> T executePost(String serviceId, String path, Object param, Class<?> responseType, boolean processPriority) {
        return this.executePost(serviceId, path, param, responseType);
    }
}
